#include "lcd_init.h"
#include "stdio.h"
#include <string.h>
// #include "app.h"

typedef void (*FunType)(void);
//**********************************write function begin********************************************
void wr_cmd_4spi_8bcs(uint8_t par)
{
    // LCD_DCXLow();
    LCD_CSLow();

    LCD_SCLLow();
    LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x80)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x40)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x20)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x10)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x08)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x04)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x02)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x01)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_CSHigh();
    // LCD_DCXHigh();
    // HAL_Delay(5);
}
void wr_dat_4spi_8bcs(uint8_t par)
{
    LCD_CSLow();
    LCD_SCLLow();
    LCD_SDAHigh();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x80)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x40)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x20)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x10)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x08)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x04)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x02)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x01)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_CSHigh();
    LCD_DCXHigh();
    // HAL_Delay(1);
}
void wr_cmd_parall1_8(uint16_t par)
{
    LCD_DCXLow();
    LCD_CSLow();
    LCD_WRLow();
    GPIOB->ODR = par;

    LCD_WRHigh();
}
void wr_dat_parall1_8(uint16_t par)
{
    LCD_DCXHigh();
    LCD_WRLow();
    GPIOB->ODR = par;

    LCD_WRHigh();
}
void wr_cmd_parall2_8(uint16_t par)
{
    LCD_DCXLow();
    LCD_CSLow();
    LCD_WRLow();
    GPIOB->ODR = par << 1;

    LCD_WRHigh();
}
void wr_dat_parall2_8(uint16_t par)
{
    LCD_DCXHigh();
    LCD_WRLow();
    GPIOB->ODR = par << 1;

    LCD_WRHigh();
}
//**********************************read function begin********************************************
void pb_out(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // db 0-7
    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
                          GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void pb_in(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // db 0-7
    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
                          GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
uint8_t i801_read_byte(void)
{
    uint8_t v;

    LCD_DCXHigh();
    LCD_RDLow();
    v = GPIOB->IDR;
    LCD_RDHigh();

    return v;
}
void rd_parall1_8(uint8_t c, uint8_t *d, uint32_t l)
{
    uint8_t buf[128];

    wr_cmd_parall1_8(c);
    pb_in();
    for (int i = 0; i < l; i++)
    {
        buf[i] = i801_read_byte();
    }
    LCD_CSHigh();
    pb_out();
    memcpy(d, buf, l);
}

void Write(uint8_t dc, uint8_t par)
{
    LCD_CSLow();

    LCD_SCLLow();
    if (dc == Command)
    {
        LCD_SDALow();
    }
    else if (dc == Parameter)
    {
        LCD_SDAHigh();
    }
    LCD_SCLHigh();

    for (uint8_t i = 0; i < 8; i++)
    {
        LCD_SCLLow();
        if ((par & 0x80) != 0)
        {
            LCD_SDAHigh();
        }
        else
        {
            LCD_SDALow();
        }
        LCD_SCLHigh();
        par = par << 1;
    }
    LCD_CSHigh();
    LCD_SCLHigh();
}

#if (0)
void Write(uint8_t dc, uint8_t par)
{
    if (dc == Command)
    {
        wr_cmd_4spi_8bcs(par);
    }
    else
    {
        wr_dat_4spi_8bcs(par);
    }
}
#endif
void HW_Reset(void)
{
    LCD_RSTHigh();
    HAL_Delay(120);
    LCD_RSTLow();
    HAL_Delay(120);
    LCD_RSTHigh();
    HAL_Delay(200);
}

void Delay(uint32_t ms)
{
    HAL_Delay(ms);
}

void WR_7789_REG(uint16_t par)
{
    Write(0, par);
}

void WR_7789_PAR(uint16_t par)
{
    Write(1, par);
}

void initial_rgb(void)
{
    HW_Reset();

    WR_7789_REG(0x11); // Exit Sleep
    Delay(120);

    //WR_7789_REG(0xB0); // RAM Control
    //WR_7789_PAR(0x11); // RM=1:RGB interface,DM[1:0]=01:RGB interface DOTCLK SYNC Mode
    //WR_7789_PAR(0xF4); // EPF[1:0]=11,ENDIAN=0,MDT[1:0]=01:3 x 6 bytes

    //WR_7789_REG(0xB1); // RGB  de mode  ?
    //WR_7789_PAR(0x60); // 40 WO=0:Memory,RCM[1:0]=11:RGB HV mode,VS=0,HS=0,CLK=positive edge,DE=1
    //WR_7789_PAR(0x04); // VS number
    //WR_7789_PAR(0x1E); // HS numbe

    WR_7789_REG(0xB2); // Porch Setting
    WR_7789_PAR(0x0C); // BPA[6:0]: Back porch setting
    WR_7789_PAR(0x0C); // FPA[6:0]: Front porch setting
    WR_7789_PAR(0X00); // PSEN
    WR_7789_PAR(0X33); // BPB[3:0]: Back porch setting,FPB[3:0]: Front porch setting
    WR_7789_PAR(0X33); // BPC[3:0]: Back porch setting,FPC[3:0]: Front porch setting

    WR_7789_REG(0xB7); // Gate Control
    WR_7789_PAR(0x65); // VGHS[2:0]: VGH=14.97V.VGLS[2:0]: VGL=-10.43

    WR_7789_REG(0xBB); // VCOMS Setting
    WR_7789_PAR(0x17); // 0.55V

    WR_7789_REG(0xC0); // LCM Control
    WR_7789_PAR(0x2C); // 0,xmy,xbgr,xinv,xmx,xmh,xmv,xgs

    WR_7789_REG(0xC2); // VDV and VRH Command Enable
    WR_7789_PAR(0x01); // Enable

    WR_7789_REG(0xC3); // VRH Set
    WR_7789_PAR(0x13); // 4.3+( vcom+vcom offset+vdv),-4.3+( vcom+vcom offset-vdv)

    WR_7789_REG(0xC4); // DV Set
    WR_7789_PAR(0x20); // 0V

    WR_7789_REG(0xC6); // Frame Rate Control in Normal Mode
    WR_7789_PAR(0x0F); // NLA[2 :0]=0:dot inversion.RTNA[4:0]=0X0F: 60 Hz

    WR_7789_REG(0xD0); // Power Control 1
    WR_7789_PAR(0xA4);
    WR_7789_PAR(0xA1); // AVDD[1:0]=02H:6.6V.AVCL[1:0]=02H:-4.8V.VDS[1:0]=01H:2.3V

    WR_7789_REG(0xD6); // Gate Output Selection in Sleep In Mode
    WR_7789_PAR(0xA1); // GATESEL=0:Gate output is GND in sleep in mode

    WR_7789_REG(0xE0); // Set Gamma1
    WR_7789_PAR(0xD0);
    WR_7789_PAR(0x0C);
    WR_7789_PAR(0x14);
    WR_7789_PAR(0x0C);
    WR_7789_PAR(0x09);
    WR_7789_PAR(0x17);
    WR_7789_PAR(0x39);
    WR_7789_PAR(0x54);
    WR_7789_PAR(0x4F);
    WR_7789_PAR(0x19);
    WR_7789_PAR(0x13);
    WR_7789_PAR(0x13);
    WR_7789_PAR(0x2D);
    WR_7789_PAR(0x34);

    WR_7789_REG(0XE1); // Set Gamma2
    WR_7789_PAR(0xD0);
    WR_7789_PAR(0x13);
    WR_7789_PAR(0x17);
    WR_7789_PAR(0x0A);
    WR_7789_PAR(0x0B);
    WR_7789_PAR(0x05);
    WR_7789_PAR(0x39);
    WR_7789_PAR(0x43);
    WR_7789_PAR(0x4D);
    WR_7789_PAR(0x36);
    WR_7789_PAR(0x11);
    WR_7789_PAR(0x12);
    WR_7789_PAR(0x2C);
    WR_7789_PAR(0x32);

    WR_7789_REG(0x35); // TE
    WR_7789_PAR(0x00);

    WR_7789_REG(0x21); // Display Inversion On

    WR_7789_REG(0x29); // display on
}

void initial(void)
{
    HW_Reset();

    Delay(120); // ms

    Write(Command, 0x11);

    Delay(120); // ms

    Write(Command, 0x36);
    Write(Parameter, 0x00);

    Write(Command, 0x3A);
    Write(Parameter, 0x66);

    Write(Command, 0xB2);
    Write(Parameter, 0x0C);
    Write(Parameter, 0x0C);
    Write(Parameter, 0x00);
    Write(Parameter, 0x33);
    Write(Parameter, 0x33);

    Write(Command, 0xB7);
    Write(Parameter, 0x75);

    Write(Command, 0xBB);
    Write(Parameter, 0x19);

    Write(Command, 0xC0);
    Write(Parameter, 0x2C);

    Write(Command, 0xC2);
    Write(Parameter, 0x01);

    Write(Command, 0xC3);
    Write(Parameter, 0x13);

    Write(Command, 0xC4);
    Write(Parameter, 0x20);

    Write(Command, 0xC6);
    Write(Parameter, 0x0F);

    Write(Command, 0xD0);
    Write(Parameter, 0xA4);
    Write(Parameter, 0xA1);

    Write(Command, 0xD6);
    Write(Parameter, 0xA1);

    Write(Command, 0xE0);
    Write(Parameter, 0xF0);
    Write(Parameter, 0x0B);
    Write(Parameter, 0x12);
    Write(Parameter, 0x0C);
    Write(Parameter, 0x0C);
    Write(Parameter, 0x09);
    Write(Parameter, 0x37);
    Write(Parameter, 0x44);
    Write(Parameter, 0x4D);
    Write(Parameter, 0x38);
    Write(Parameter, 0x13);
    Write(Parameter, 0x11);
    Write(Parameter, 0x2E);
    Write(Parameter, 0x34);

    Write(Command, 0xE1);
    Write(Parameter, 0xF0);
    Write(Parameter, 0x09);
    Write(Parameter, 0x0F);
    Write(Parameter, 0x08);
    Write(Parameter, 0x08);
    Write(Parameter, 0x23);
    Write(Parameter, 0x37);
    Write(Parameter, 0x43);
    Write(Parameter, 0x4C);
    Write(Parameter, 0x35);
    Write(Parameter, 0x10);
    Write(Parameter, 0x12);
    Write(Parameter, 0x2C);
    Write(Parameter, 0x32);

    Write(Command, 0x21);

    Write(Command, 0x29);

    Write(Command, 0x2C);
}

void C096LAB_Init(void)
{
    HW_Reset();

    Delay(120); // ms

    Write(Command, 0x11);

    Delay(120); // ms

    Write(Command, 0x36);
    Write(Parameter, 0x00);

    Write(Command, 0x3A);
    Write(Parameter, 0x66);

    Write(Command, 0xB2);
    Write(Parameter, 0x0C);
    Write(Parameter, 0x0C);
    Write(Parameter, 0x00);
    Write(Parameter, 0x33);
    Write(Parameter, 0x33);

    Write(Command, 0xB7);
    Write(Parameter, 0x75);

    Write(Command, 0xBB);
    Write(Parameter, 0x19);

    Write(Command, 0xC0);
    Write(Parameter, 0x2C);

    Write(Command, 0xC2);
    Write(Parameter, 0x01);

    Write(Command, 0xC3);
    Write(Parameter, 0x13);

    Write(Command, 0xC4);
    Write(Parameter, 0x20);

    Write(Command, 0xC6);
    Write(Parameter, 0x0F);

    Write(Command, 0xD0);
    Write(Parameter, 0xA4);
    Write(Parameter, 0xA1);

    Write(Command, 0xD6);
    Write(Parameter, 0xA1);

    Write(Command, 0xE0);
    Write(Parameter, 0xF0);
    Write(Parameter, 0x0B);
    Write(Parameter, 0x12);
    Write(Parameter, 0x0C);
    Write(Parameter, 0x0C);
    Write(Parameter, 0x09);
    Write(Parameter, 0x37);
    Write(Parameter, 0x44);
    Write(Parameter, 0x4D);
    Write(Parameter, 0x38);
    Write(Parameter, 0x13);
    Write(Parameter, 0x11);
    Write(Parameter, 0x2E);
    Write(Parameter, 0x34);

    Write(Command, 0xE1);
    Write(Parameter, 0xF0);
    Write(Parameter, 0x09);
    Write(Parameter, 0x0F);
    Write(Parameter, 0x08);
    Write(Parameter, 0x08);
    Write(Parameter, 0x23);
    Write(Parameter, 0x37);
    Write(Parameter, 0x43);
    Write(Parameter, 0x4C);
    Write(Parameter, 0x35);
    Write(Parameter, 0x10);
    Write(Parameter, 0x12);
    Write(Parameter, 0x2C);
    Write(Parameter, 0x32);

    Write(Command, 0x21);

    Write(Command, 0x29);

    Write(Command, 0x2C);

    wr_cmd_4spi_8bcs(0x2C);
}
